系统参数:如何按业务场景优化网络性能

2023/2/7

# 写在前面

了解计算机的都知道,计算机的操作系统管理着它的各种资源,其中就包括网络设备。可以说,网络设备相当于互联网的神经元,计算机依靠它互相通信。如果网络通信性能很差,会导致计算机的处理能力无法充分利用起来,进而影响我们所要设计的软件系统,所以优化网络性能就显得非常重要 那么,在不增加网络设备成本的前提下,我们该如何提升网络性能呢?答案是可以通过 优化系统参数 来提升;为什么?因为网络协议是由操作系统来处理的,而操作系统有很多网络协议相关的参数,如果这些参数配置错了,无疑会降低网络性能

  1. 以秒杀系统为例,秒杀需要的各个商品图片通常是存放在图片存储系统中的。虽然这些图片一般会在前端缓存下来以便提升图片加载速度,(如果没有使用 CDN)但浏览器第一次访问的时候还是需要从图片存储系统获取图片。如果单个图片几MB 甚至几十MB,一旦过多,无疑会影响图片存储系统的性能。所以对于图片存储系统,我们可以通过优化网络连接缓冲区的相关参数来提升性能
  2. 再比如秒杀接口,因为用户参与多,它需要处理大量秒杀请求,如果想要提升请求速度,可以通过优化快速处理网络连接和请求相关的参数来实现

# 系统参数相关

Linux 系统参数有一千多个,这么多参数对应不同的作用,我们该如何选择合适的参数来优化呢?首先,我们可以先找到所有的系统参数,在 Linux 系统中执行命令:

sudo /sbin/sysctl -a

一般来说,不同的参数类型对应不同的资源和性能,进而影响不同的业务场景,比如网络参数主要影响以网络请求为主的业务,文件系统参数主要影响以读写文件为主的业务场景。那我们该如何获取参数类型呢,可以执行以下命令:

sudo /sbin/sysctl -a|awk -F "." '{print $1}'|sort -k1|uniq

结果如下所示:

abi
debug
fs
kernel
net
user
vm

其中 net 类型就是我们需要重点关注的,因为它几乎包含了网络性能优化相关的全部参数。通过执行以下命令:

sudo /sbin/sysctl -a|grep "^net."|awk -F "[.| ]" '{print $2}'|sort -k1|uniq

我们将得到 net 类型下所有子类型:

bridge
core
ipv4
ipv6
netfilter
nf_conntrack_max
unix

在 Linux 系统里,这些参数都可以在 /etc/sysctl.conf 文件里修改,如果没有,你可以自行添加。修改完后,可以使用 sudo sysctl -p 命令加载最新配置,让配置生效 在这些子类型当中,我们需要重点关注 core 和 ipv4 的配置。 因为这两类配置里包含网络协议相关的各种参数,前面我提到的秒杀接口服务和图片存储系统这两个业务场景,就需要 core 和 ipv4 中的参数来优化

# 了解套件字缓冲区参数

在程控电话出现以前,人们打电话需要通过接线员把通信双方的电话线套接在一起来接通。在计算机网络通信出现以后,我们便用套接字来表示双向网络通信的端点。而网络套接字缓冲区的大小直接影响程序通过网络收发数据的性能 就像我们前面提到的图片存储系统,它主要是处理图片文件数据。如果网络套接字缓冲区太小,会导致程序读写多次之后才能将数据处理完,这大大影响了程序性能。如果缓冲区足够大,程序能很快将处理好的数据写入缓冲区,接着就可以去忙别的事了,这无疑提升了运行效率 那么,套接字缓冲区的大小怎样设置呢?就是通过系统参数来设置。具体参数我们可以在终端执行以下命令来获取:

sudo /sbin/sysctl -a|grep "^net."|grep "[r|w|_]mem[_| ]"

image.png

# 如何优化 TCP 协议参数和最大连接数

熟悉 TCP 协议的同学应该对 TCP 中的“三次握手”“四次挥手”“慢启动”“滑动窗口”“超时重传”“粘包算法”等机制不陌生,正是这些机制确保了 TCP 的可靠传输。但是,有时候,这些机制反而会成为网络瓶颈

比如,当网络带宽非常好的时候,“慢启动”机制反而会限制数据传输速度。再比如,“粘包算法”会将一些小的数据包合并成一个 TCP 包发出去,或者一直等到定时器超时后发送。在某些情况下该算法确实能提升网络吞吐量,但对于一些对实时性要求较高的数据来说,它会导致接收方无法及时接收到数据

秒杀的抢购接口,负责接收大量用户的抢购请求。对于有资格的用户,执行扣减库存并下单然后返回抢购成功给前端;对于没有资格或者扣减库存失败的用户,则返回抢购失败给前端。发起抢购请求以及请求返回的 HTTP 协议数据大概在 500 字节,秒杀接口服务需要快速处理连接的建立、断开、回收。那么,该如何优化秒杀接口服务的网络参数提升处理网络连接的性能呢?

# 关闭粘包算法

首先,我们知道,秒杀接口服务是通过公网给用户提供服务的,而公网的数据帧能承载的应用数据是 1472 字节。秒杀抢购接口处理的数据大小 500 字节相当于 1472 的 1/3,由此可以判断这些数据包是小数据包,可能会受“粘包算法”影响。然而,用户对请求的耗时很敏感,这就需要关闭“粘包算法”,确保数据包立即投递出去。怎么做呢?可以在 TCP 套接字加上 TCP_NODELAY 参数来关闭该算法

# 复用套接字

秒杀用户量大,这就需要秒杀接口服务处理大量短连接,由此会导致什么结果呢?需要秒杀接口服务创建、回收套接字的速度非常快,以便有足够资源处理大量连接。怎么办?我们可以通过关闭空闲连接、复用套接字等方法快速回收或重用已分配的资源。具体设置如下:

# 重用处于 TIME-WAIT 状态的套接字
net.ipv4.tcp_tw_reuse = 1

# 快速回收 TIME-WAIT 状态的套接字
net.ipv4.tcp_tw_recycle = 1

# 关闭处于 FIN-WAIT-2 状态 30 秒以上的套接字
net.ipv4.tcp_fin_timeout = 30

# 设置空闲 TCP 连接存活时间,以便即时关闭空闲连接,回收资源
net.ipv4.tcp_keepalive_time=1800

# 超时重传

由于秒杀请求量大,偶尔的网络抖动可能导致部分数据包丢失,这将会触发“超时重传”。为了避免重传网络抖动后的所有包,我们可以设置选择性重传的参数,避免重传已成功发送的数据包,导致浪费网络带宽。具体的办法是,将 net.ipv4.tcp_sack 这一参数设置为 1

# 文件描述符数量

秒杀活动中用户日活达到了百万以上,这就需要尽可能提升单机网络连接容量,确保并发能力。在操作系统中,一个网络连接会占用一个文件描述符,这需要将最大文件打开数的参数设置为一个比较大的值,以免文件描述符不够用导致性能问题。如 fs.file-max = 65535 表示最多可以打开 65535 个文件